#include <stdio.h>
#include <memory.h>
#include "sm_trace.h"
#include "itc.h"
#include "xmsg.h"
#include "app_proxy.h"
#include "common.h"
#include "sas.h"
#include "mmi.h"


typedef enum
{
	PSS_NOTUSED,
	PSS_CREATING,
	PSS_CREATED,
}proxy_sess_status_t;

#define PROXY_SESS_COUNT	128
static struct
{
	proxy_sess_status_t	m_status;
	unsigned short 		m_ssnb;
	unsigned char 		m_tcid;
	unsigned char 		m_ressIndex;
}s_proxy_tab_sess[PROXY_SESS_COUNT];


resource_t g_tab_ress[RESOURCE_COUNT];
static unsigned int s_dwRessCnt = 0;

unsigned int s_dwPrivateRessCnt = 0;


static int app_proxy_init(void)
{
	int i;

	SM_TRACE_ENTRY(TRMOD_APP, "app_proxy_init() - entry\r\n");

	if (ITC_Init(RM) <= 0)
	{
		SM_TRACE_ERROR(TRMOD_APP,"app_proxy_init() - itc init failed\r\n");
		return -1;
	}

	s_dwRessCnt = 0;
	//RM: Resource Mangager.
	g_tab_ress[s_dwRessCnt].m_ressId=RM_RESOURCE_ID;
	g_tab_ress[s_dwRessCnt].m_isLocalRess=1;
	g_tab_ress[s_dwRessCnt].m_funOnMessage=rm_on_message;
	s_dwRessCnt++;

	//AI: Applicatiion Information.
	g_tab_ress[s_dwRessCnt].m_ressId=AI_RESOURCE_ID;
	g_tab_ress[s_dwRessCnt].m_isLocalRess=1;
	g_tab_ress[s_dwRessCnt].m_funOnMessage=ai_on_message;
	s_dwRessCnt++;

	//CAS: Conditional Access Support.
	g_tab_ress[s_dwRessCnt].m_ressId=CAS_RESOURCE_ID;
	g_tab_ress[s_dwRessCnt].m_isLocalRess=1;
	g_tab_ress[s_dwRessCnt].m_funOnMessage=cas_on_message;
	s_dwRessCnt++;

	//DT: Date and Time.
	g_tab_ress[s_dwRessCnt].m_ressId=DT_RESOURCE_ID;
	g_tab_ress[s_dwRessCnt].m_isLocalRess=1;
	g_tab_ress[s_dwRessCnt].m_funOnMessage=dt_on_message;
	s_dwRessCnt++;

	//MMI: Man Machine Interface.
	g_tab_ress[s_dwRessCnt].m_ressId=MMI_RESOURCE_ID;
	g_tab_ress[s_dwRessCnt].m_isLocalRess=1;
	g_tab_ress[s_dwRessCnt].m_funOnMessage=mmi_on_message;
	s_dwRessCnt++;

	//SAS: Special Application Support.
	g_tab_ress[s_dwRessCnt].m_ressId=SAS_RESOURCE_ID;
	g_tab_ress[s_dwRessCnt].m_isLocalRess=1;
	g_tab_ress[s_dwRessCnt].m_funOnMessage=sas_on_message;
	s_dwRessCnt++;

	//HC: Host Control.
	g_tab_ress[s_dwRessCnt].m_ressId=CI_HC_RESOURCE_ID_V1;
	g_tab_ress[s_dwRessCnt].m_isLocalRess=1;
	g_tab_ress[s_dwRessCnt].m_funOnMessage=hc_on_message;
	s_dwRessCnt++;

	if(rm_init())
	{
		SM_TRACE_ERROR(TRMOD_APP,"app_proxy_init() - rm init error\n");
		return -1;
	}

	if(dt_init())
	{
		SM_TRACE_ERROR(TRMOD_APP,"app_proxy_init() - dt init errro\n");
		return -1;
	}

	if(ai_init())
	{
		SM_TRACE_ERROR(TRMOD_APP,"app_proxy_init() - ai init errro\n");
		return -1;
	}

	if(cas_init())
	{
		SM_TRACE_ERROR(TRMOD_APP,"app_proxy_init() - cas init errro\n");
		return -1;
	}

	if(mmi_init())
	{
		SM_TRACE_ERROR(TRMOD_APP,"app_proxy_init() - mmi init errro\n");
		return -1;
	}

	if(sas_init())
	{
		SM_TRACE_ERROR(TRMOD_APP,"app_proxy_init() - sas init errro\n");
		return -1;
	}

	if(hc_init())
	{
		SM_TRACE_ERROR(TRMOD_APP,"app_proxy_init() - hc init errro\n");
		return -1;
	}


	for(i=0; i<PROXY_SESS_COUNT; i++)
	{
		s_proxy_tab_sess[i].m_status=PSS_NOTUSED;
	}

	SM_TRACE_RETURN(TRMOD_APP, "app_proxy_init() - return 0\r\n");
	return 0;
}


static void proxy_end(void)
{
	SM_TRACE_ENTRY(TRMOD_APP, "proxy_end() - entry\r\n");

	ITC_End();

	SM_TRACE_RETURN(TRMOD_APP, "proxy_end() - return\r\n");
	return;
}

static int proxy_on_rcv_app_open_ss_rsp(xmsg_t* pXmsg)
{
	int				i;
	xmsg_t			xmsg;

	SM_TRACE_ENTRY(TRMOD_APP,"proxy_on_rcv_app_open_ss_rsp() - entry, "
					"pXmsg=0x%08X\r\n", pXmsg);

		for(i=0; i < PROXY_SESS_COUNT; i++)
		{
			if((s_proxy_tab_sess[i].m_status==PSS_CREATING)
				&&(s_proxy_tab_sess[i].m_ssnb==pXmsg->m_bd.m_app_open_ss_rsp.m_ssnb))
			{
				break;
			}
		}
		if (i >= PROXY_SESS_COUNT)
		{
			SM_TRACE_ERROR(TRMOD_APP,"proxy_on_rcv_app_open_ss_rsp() - sess not found\r\n");
			return 0;
		}

		if (pXmsg->m_bd.m_app_open_ss_rsp.m_status != 0) // status 0 is ok, other is failed
			s_proxy_tab_sess[i].m_status=PSS_NOTUSED;

		memset(&xmsg, 0x00, sizeof(xmsg));
		xmsg.m_sndrcver   = (RM << 4) | SESS;
		xmsg.m_type       = RM_OPEN_SS_RSP;
		xmsg.m_bd.m_rm_open_ss_rsp.m_rtcid = pXmsg->m_bd.m_app_open_ss_rsp.m_rtcid;
		xmsg.m_bd.m_rm_open_ss_rsp.m_ssnb  = pXmsg->m_bd.m_app_open_ss_rsp.m_ssnb;
		xmsg.m_bd.m_rm_open_ss_rsp.m_status = pXmsg->m_bd.m_app_open_ss_rsp.m_status;
		xmsg.m_bd.m_rm_open_ss_rsp.m_ressId = g_tab_ress[s_proxy_tab_sess[i].m_ressIndex].m_ressId;
		SM_TRACE_INFO(TRMOD_APP,"proxy_on_rcv_app_open_ss_rsp() - will send RM_OPEN_SS_RSP to SESS\r\n");
		ITC_SendXmsg(&xmsg);

	SM_TRACE_RETURN(TRMOD_APP, "proxy_on_rcv_app_open_ss_rsp() - return\r\n");
	return 0;
}


static void proxy_on_rcv_rm_open_ss_req(xmsg_t* pXmsg)
{
	//received RM_OPEN_SS_REQ from sess task, send APP_OPEN_SS_REQ to resource entity
	int				proxySessIndex;
	int				ressIndex;
	unsigned long	ressId;
	unsigned short	ssnb;
	unsigned char	tcid;
	xmsg_t			xmsg;

	SM_TRACE_ENTRY(TRMOD_APP, "proxy_on_rcv_rm_open_ss_req() - entry,pXmsg=0x%08X\r\n", pXmsg);

	tcid = pXmsg->m_bd.m_rm_open_ss_req.m_tcid;
	ssnb = pXmsg->m_bd.m_rm_open_ss_req.m_ssnb;
	ressId = pXmsg->m_bd.m_rm_open_ss_req.m_ressId;

	//check the resource in resource table
	for(ressIndex=0;ressIndex<RESOURCE_COUNT;ressIndex++)
	{
		if(!g_tab_ress[ressIndex].m_ressId) //empty entry
			continue;

		if(g_tab_ress[ressIndex].m_ressId==ressId)//exactly the same resource.
			break;

		if((PRIVATE_RESOURCE_ID_TYPE!=(ressId&RESOURCE_ID_TYPE_MASK)) //public resource
			&&((g_tab_ress[ressIndex].m_ressId&RESOURCE_CLASS_MASK)==(ressId&RESOURCE_CLASS_MASK))
			&&((g_tab_ress[ressIndex].m_ressId&RESOURCE_TYPE_MASK)==(ressId&RESOURCE_TYPE_MASK)))
		{
			break;//same class and type
		}
	}

	if (ressIndex>=RESOURCE_COUNT)
	{
		SM_TRACE_ERROR(TRMOD_APP,"proxy_on_rcv_rm_open_ss_req() - not found ressId=0x%08X\r\n", ressId);
		memset(&xmsg, 0x00, sizeof(xmsg));
		xmsg.m_sndrcver   = (RM << 4) | SESS;
		xmsg.m_type       = RM_OPEN_SS_RSP;
		xmsg.m_bd.m_rm_open_ss_rsp.m_rtcid = 0;
		xmsg.m_bd.m_rm_open_ss_rsp.m_ssnb  = ssnb;
		xmsg.m_bd.m_rm_open_ss_rsp.m_status = SS_NOTALLOCATED; //no resource found
		xmsg.m_bd.m_rm_open_ss_rsp.m_ressId = ressId;
		ITC_SendXmsg(&xmsg);
		return;
	}

	if( (PRIVATE_RESOURCE_ID_TYPE != (ressId & RESOURCE_ID_TYPE_MASK))
		&& ((ressId & RESOURCE_VERSION_MASK)
		> (g_tab_ress[ressIndex].m_ressId & RESOURCE_VERSION_MASK)))
	{
		//public resource, but the version not match.
		memset(&xmsg, 0x00, sizeof(xmsg));
		xmsg.m_sndrcver   = (RM << 4) | SESS;
		xmsg.m_type       = RM_OPEN_SS_RSP;
		xmsg.m_bd.m_rm_open_ss_rsp.m_rtcid = 0;
		xmsg.m_bd.m_rm_open_ss_rsp.m_ssnb  = ssnb;
		xmsg.m_bd.m_rm_open_ss_rsp.m_status = SS_BADVERSION;
		xmsg.m_bd.m_rm_open_ss_rsp.m_ressId = g_tab_ress[ressIndex].m_ressId;
		ITC_SendXmsg(&xmsg);
		return;
	}

	if(g_tab_ress[ressIndex].m_isLocalRess==0) //remote resouce
	{
		memset(&xmsg, 0x00, sizeof(xmsg));
		xmsg.m_sndrcver   = (RM << 4) | SESS;
		xmsg.m_type       = RM_OPEN_SS_RSP;
		xmsg.m_bd.m_rm_open_ss_rsp.m_rtcid = g_tab_ress[ressIndex].m_tcid;
		xmsg.m_bd.m_rm_open_ss_rsp.m_ssnb  = ssnb;
		xmsg.m_bd.m_rm_open_ss_rsp.m_status = 0;
		xmsg.m_bd.m_rm_open_ss_rsp.m_ressId = g_tab_ress[ressIndex].m_ressId;
		ITC_SendXmsg(&xmsg);
		return;
	}

	//local resource
	for(proxySessIndex=0;proxySessIndex<PROXY_SESS_COUNT; proxySessIndex++)
	{
		if(s_proxy_tab_sess[proxySessIndex].m_status==PSS_NOTUSED) //empty entry
			break;
	}
	if (proxySessIndex >= PROXY_SESS_COUNT)
	{
		SM_TRACE_ERROR(TRMOD_APP,"proxy_on_rcv_rm_open_ss_req() - proxy sess table exausted, just ignore this request");
		return;
	}

	//add a element to the proxy sess table
	s_proxy_tab_sess[proxySessIndex].m_status=PSS_CREATING;
	s_proxy_tab_sess[proxySessIndex].m_ssnb=ssnb;
	s_proxy_tab_sess[proxySessIndex].m_tcid=tcid;
	s_proxy_tab_sess[proxySessIndex].m_ressIndex=ressIndex;

	memset(&xmsg, 0x00, sizeof(xmsg));
	xmsg.m_sndrcver = (RM << 4) | RM;
	xmsg.m_type  = APP_OPEN_SS_REQ;
	xmsg.m_bd.m_app_open_ss_req.m_tcid = tcid;
	xmsg.m_bd.m_app_open_ss_req.m_ssnb = ssnb;
	xmsg.m_bd.m_app_open_ss_req.m_ressId = ressId;
	SM_TRACE_INFO(TRMOD_APP,"proxy_on_rcv_rm_open_ss_req() - dispatch APP_OPEN_SS_REQ to resource entity\r\n");
	g_tab_ress[ressIndex].m_funOnMessage(&xmsg);

	SM_TRACE_RETURN(TRMOD_APP, "proxy_on_rcv_rm_open_ss_req() - return\r\n");
}


void send_app_apdu_to_proxy(unsigned short ssnb, unsigned long apduTag,
				unsigned char* pbApduBody, int apduBodyLen)
{
	xmsg_t		xmsg;
	int			apduLen;
	int			sizeLenfield;

	memset(&xmsg, 0x00, sizeof(xmsg));
	sizeLenfield = asnWriteApduLengthField(NULL, apduBodyLen);
	apduLen = 3 + sizeLenfield + apduBodyLen; //apdutag+lengthfield+body
	xmsg.m_bd.m_app_apdu.m_pbApdu = ITC_DynAlloc(apduLen);
	if (xmsg.m_bd.m_app_apdu.m_pbApdu == NULL)
	{
		SM_TRACE_INFO(TRMOD_APP,"send_app_apdu_to_proxy() - mem alloc error");
		return;
	}

	xmsg.m_sndrcver = (RM << 4) | RM;
	xmsg.m_type  = APP_APDU;
	xmsg.m_bd.m_app_apdu.m_ssnb = ssnb;
	xmsg.m_bd.m_app_apdu.m_apduLen = apduLen;
	xmsg.m_bd.m_app_apdu.m_pbApdu[0] = (unsigned char)((apduTag>>16)&0xFF);
	xmsg.m_bd.m_app_apdu.m_pbApdu[1] = (unsigned char)((apduTag>>8)&0xFF);
	xmsg.m_bd.m_app_apdu.m_pbApdu[2] = (unsigned char)((apduTag>>0)&0xFF);
	asnWriteApduLengthField(xmsg.m_bd.m_app_apdu.m_pbApdu+3, apduBodyLen);
	if (apduBodyLen > 0)
		memcpy(xmsg.m_bd.m_app_apdu.m_pbApdu + 3 + sizeLenfield, pbApduBody, apduBodyLen);

	ITC_SendXmsg(&xmsg);
}


static void proxy_on_rcv_app_apdu(xmsg_t* pXmsg)
{
	// received APP_APDU from resource entity, send APDU to sess task
	int				i;
	xmsg_t			xmsg;
	unsigned short	ssnb;
	int				apduLen;

	SM_TRACE_ENTRY(TRMOD_APP,"proxy_on_rcv_app_apdu() - entry, pXmsg=0x%08X\r\n", pXmsg);

	ssnb=pXmsg->m_bd.m_app_apdu.m_ssnb;
	apduLen = pXmsg->m_bd.m_app_apdu.m_apduLen;
	SM_ASSERT(apduLen);
	SM_ASSERT(pXmsg->m_bd.m_app_apdu.m_pbApdu);

	for(i=0;i<PROXY_SESS_COUNT; i++)
	{
		if((s_proxy_tab_sess[i].m_status==PSS_CREATED)
			&&(s_proxy_tab_sess[i].m_ssnb==ssnb))
		{
			break;
		}
	}
	if (i >= PROXY_SESS_COUNT)
	{
		SM_TRACE_ERROR(TRMOD_APP,"proxy_on_rcv_app_apdu() - invalid ssnb=%d\r\n", ssnb);
		return;
	}

	memset(&xmsg, 0x00, sizeof(xmsg));
	xmsg.m_bd.m_apdu.m_pbApdu = pXmsg->m_bd.m_app_apdu.m_pbApdu;
	xmsg.m_sndrcver  = (RM<<4)|SESS;
	xmsg.m_type     = APDU;
	xmsg.m_bd.m_apdu.m_ssnb    = ssnb;
	xmsg.m_bd.m_apdu.m_len  	= apduLen;

	SM_TRACE_INFO(TRMOD_APP,"proxy_on_rcv_app_apdu() - send APDU to sess task\r\n");
	if (!ITC_SendXmsg(&xmsg))
	{
		SM_TRACE_ERROR(TRMOD_APP,"proxy_on_rcv_app_apdu() - send xmsg failed\r\n");
		return;
	}

	pXmsg->m_bd.m_app_apdu.m_pbApdu = NULL;

	SM_TRACE_RETURN(TRMOD_APP, "proxy_on_rcv_app_apdu() - return\r\n");
}


void proxy_on_rcv_rm_apdu(xmsg_t* pXmsg)
{
	// received APDU from sess task, send APP_APDU to resource entity
	int				i;
	xmsg_t			xmsg;
	unsigned short	ssnb;
	int				apduLen;

	SM_TRACE_ENTRY(TRMOD_APP,"proxy_on_rcv_rm_apdu() - entry, pXmsg=0x%08X\r\n", pXmsg);

	ssnb = pXmsg->m_bd.m_apdu.m_ssnb ;
	apduLen  = pXmsg->m_bd.m_apdu.m_len ;
	SM_ASSERT(apduLen);
	SM_ASSERT(pXmsg->m_bd.m_apdu.m_pbApdu);

	for(i=0; i<PROXY_SESS_COUNT; i++)
	{
		if((s_proxy_tab_sess[i].m_status==PSS_CREATED)
			&&(s_proxy_tab_sess[i].m_ssnb==ssnb))
		{
			break;
		}
	}
	if (i >= PROXY_SESS_COUNT)
	{
		SM_TRACE_INFO(TRMOD_APP,"proxy_on_rcv_rm_apdu() - not found ssnb=%d\r\n", ssnb);
		return;
	}

	memset(&xmsg, 0x00, sizeof(xmsg));
	xmsg.m_sndrcver = (RM << 4) | RM;
	xmsg.m_type  = APP_APDU;
	xmsg.m_bd.m_app_apdu.m_tcid = s_proxy_tab_sess[i].m_tcid;
	xmsg.m_bd.m_app_apdu.m_ssnb = ssnb;
	xmsg.m_bd.m_app_apdu.m_apduLen = apduLen;
	xmsg.m_bd.m_app_apdu.m_pbApdu = pXmsg->m_bd.m_apdu.m_pbApdu;

	SM_TRACE_INFO(TRMOD_APP,"proxy_on_rcv_rm_apdu() - dispatch APP_APDU to resource entity\r\n");
	g_tab_ress[s_proxy_tab_sess[i].m_ressIndex].m_funOnMessage(&xmsg);

	FreeXmsg(&xmsg);
	pXmsg->m_bd.m_apdu.m_pbApdu = NULL;

	SM_TRACE_RETURN(TRMOD_APP, "proxy_on_rcv_rm_apdu() - return\r\n");
}


void proxy_state(xmsg_t* pXmsg)
{

	int i; //, j, k;
	int				proxySessIndex;
	unsigned char	tcid ;
	unsigned short	len = 0;
	unsigned short	ssnb = 0;
	xmsg_t			xmsg;

	SM_TRACE_ENTRY(TRMOD_APP, "proxy_state() - entry,pXmsg=0x%08X\r\n", pXmsg);

	SM_TRACE_INFO(TRMOD_APP,"proxy_state() - received %s(0x%02X)\r\n",
				XMSG_NAME(pXmsg->m_type), pXmsg->m_type);

	switch (pXmsg->m_type)
	{
	case RM_TC_CREATED :
		SM_TRACE_INFO(TRMOD_APP,"proxy_state() - RM_TC_CREATED received\r\n");
		tcid = pXmsg->m_bd.m_rm_tc_created.m_tcid ;
		break;

	case RM_TC_DELETED :
		SM_TRACE_INFO(TRMOD_APP,"proxy_state() - RM_TC_DELETED received\r\n");
		tcid = pXmsg->m_bd.m_rm_tc_deleted.m_tcid ;
		for(i=0; i<PROXY_SESS_COUNT; i++)
		{
			if(s_proxy_tab_sess[i].m_status!=PSS_NOTUSED)
			{
				//break all the session originating from this tc.
				if(s_proxy_tab_sess[i].m_tcid!=tcid)
					continue;

				memset(&xmsg, 0x00, sizeof(xmsg));
				xmsg.m_sndrcver = (RM << 4) | RM;
				xmsg.m_type  = APP_SS_BROKEN;
				xmsg.m_bd.m_app_ss_broken.m_ssnb = s_proxy_tab_sess[i].m_ssnb;
				g_tab_ress[s_proxy_tab_sess[i].m_ressIndex].m_funOnMessage(&xmsg);
				s_proxy_tab_sess[i].m_status=PSS_NOTUSED;
			}
		}
		for(i=0;i<RESOURCE_COUNT;i++) //finding RM
		{
			if((g_tab_ress[i].m_ressId)&&(g_tab_ress[i].m_isLocalRess==1))
			{
				if((g_tab_ress[i].m_ressId&RESOURCE_ID_TYPE_MASK) != PRIVATE_RESOURCE_ID_TYPE) //public resource
				{
					if(g_tab_ress[i].m_ressId==RM_RESOURCE_ID) //notify the RM of the broken of the tc
					{
						memset(&xmsg, 0x00, sizeof(xmsg));
						xmsg.m_sndrcver = (RM << 4) | RM;
						xmsg.m_type  = APP_TC_BROKEN;
						xmsg.m_bd.m_app_tc_broken.m_tcid = tcid;
						g_tab_ress[i].m_funOnMessage(&xmsg);
						break;
					}
				}
			}
		}
		break;

	case RM_OPEN_SS_REQ :
		SM_TRACE_INFO(TRMOD_APP,"proxy_state() - RM_OPEN_SS_REQ received\r\n");
		proxy_on_rcv_rm_open_ss_req(pXmsg);
		break;

	case RM_SS_CLOSED :
		ssnb = pXmsg->m_bd.m_rm_ss_closed.m_ssnb ;
		SM_TRACE_INFO(TRMOD_APP,"proxy_state() - RM_SS_CLOSED received\r\n");
		for(i=0;i<PROXY_SESS_COUNT;i++)
		{
			if((s_proxy_tab_sess[i].m_status==PSS_CREATED)
				&&(s_proxy_tab_sess[i].m_ssnb==ssnb))
			{
				memset(&xmsg, 0x00, sizeof(xmsg));
				xmsg.m_sndrcver = (RM << 4) | RM;
				xmsg.m_type  = APP_SS_BROKEN;
				xmsg.m_bd.m_app_ss_broken.m_ssnb = ssnb;
				g_tab_ress[s_proxy_tab_sess[i].m_ressIndex].m_funOnMessage(&xmsg);
				s_proxy_tab_sess[i].m_status=PSS_NOTUSED;
				break;
			}
		}
		break;

	case RM_SS_OPENED :
		ssnb = pXmsg->m_bd.m_rm_ss_opened.m_ssnb;
		tcid = pXmsg->m_bd.m_rm_ss_opened.m_tcid;
		SM_TRACE_INFO(TRMOD_APP,"proxy_state() - RM_SS_OPENED received,ssnb=%d\r\n", ssnb);
		for(proxySessIndex=0;proxySessIndex<PROXY_SESS_COUNT;proxySessIndex++)
		{
			if((s_proxy_tab_sess[proxySessIndex].m_status==PSS_CREATING)
				&& (s_proxy_tab_sess[proxySessIndex].m_ssnb==ssnb))
			{
				break;
			}
		}
		if (proxySessIndex >= PROXY_SESS_COUNT)
		{
			SM_TRACE_ERROR(TRMOD_APP,"proxy_state() - not found ssnb=%d\r\n",
						ssnb);
			break;
		}

		memset(&xmsg, 0x00, sizeof(xmsg));
		xmsg.m_sndrcver = (RM << 4) | RM;
		xmsg.m_type  = APP_SS_OPENED;
		xmsg.m_bd.m_app_ss_opened.m_tcid = tcid;
		xmsg.m_bd.m_app_ss_opened.m_ssnb = ssnb;

		g_tab_ress[s_proxy_tab_sess[proxySessIndex].m_ressIndex].m_funOnMessage(&xmsg);

		s_proxy_tab_sess[proxySessIndex].m_status=PSS_CREATED;
		break;

	case APP_OPEN_SS_RSP:
		SM_TRACE_INFO(TRMOD_APP,"proxy_state() - APP_OPEN_SS_RSP received\r\n");
		proxy_on_rcv_app_open_ss_rsp(pXmsg);
		break;

	case APP_CLOSE_SS_REQ:
		ssnb = pXmsg->m_bd.m_app_close_ss_req.m_ssnb ;
		SM_TRACE_INFO(TRMOD_APP,"proxy_state() - APP_CLOSE_SS_REQ received,ssnb=%d\r\n", ssnb);
		for(i=0;i<PROXY_SESS_COUNT; i++)
		{
			if((s_proxy_tab_sess[i].m_status==PSS_CREATED)
				&&(s_proxy_tab_sess[i].m_ssnb==ssnb))
			{
				memset(&xmsg, 0x00, sizeof(xmsg));
				xmsg.m_sndrcver = (RM << 4) | SESS;
				xmsg.m_type  = RM_CLOSE_SS;
				xmsg.m_bd.m_rm_close_ss.m_ssnb = ssnb;
				ITC_SendXmsg(&xmsg);
				s_proxy_tab_sess[i].m_status=PSS_NOTUSED;
				break;
			}
		}
		break;

	case APP_TMPEND:
		SM_TRACE_INFO(TRMOD_APP,"proxy_state() - APP_TMPEND received\r\n");
		ssnb = (unsigned short)pXmsg->m_bd.m_timer.m_param;
		for(i=0;i<PROXY_SESS_COUNT;i++)
		{
			if((s_proxy_tab_sess[i].m_status==PSS_CREATED)
				&&(s_proxy_tab_sess[i].m_ssnb==ssnb))
			{
				memset(&xmsg, 0x00, sizeof(xmsg));
				xmsg.m_sndrcver = (RM << 4) | RM;
				xmsg.m_type  = APP_TMPEND;
				xmsg.m_bd.m_timer.m_param = pXmsg->m_bd.m_timer.m_param;
				xmsg.m_bd.m_timer.m_timerId = pXmsg->m_bd.m_timer.m_timerId;
				g_tab_ress[s_proxy_tab_sess[i].m_ressIndex].m_funOnMessage(&xmsg);
				break;
			}
		}
		break;

	case APDU:
		SM_TRACE_INFO(TRMOD_APP,"proxy_state() - APDU received on session: %d\r\n", pXmsg->m_bd.m_apdu.m_ssnb);
		proxy_on_rcv_rm_apdu(pXmsg);
		break;

	case APP_APDU:
		SM_TRACE_INFO(TRMOD_APP,"proxy_state() - APP_APDU received\r\n");
		proxy_on_rcv_app_apdu(pXmsg);
		break;

	default:
		SM_TRACE_ERROR(TRMOD_APP,"proxy_state() - invalid message\r\n") ;
		break ;
	}

	SM_TRACE_RETURN(TRMOD_APP, "proxy_state() - return\r\n");
}


int appproxy_task(void* param)
{
	int			rc = 0;
	xmsg_t		xmsg;

	SM_TRACE_CRITICAL(TRMOD_APP, "appproxy_task() - entry\r\n");

	if (app_proxy_init())
	{
		SM_TRACE_ERROR(TRMOD_APP,"appproxy_task() - initialize ext task error\r\n");
		rc = -1;
	}

	while (rc == 0)
	{
		SM_TRACE_INFO(TRMOD_APP, "appproxy_task() - wait event infinite...\r\n");
		if (!ITC_RecvXmsg(&xmsg, ITC_INFINITE))
		{
			SM_TRACE_ERROR(TRMOD_APP,"appproxy_task() -Error in return code");
			rc = -1;
			break;
		}

		if (xmsg.m_type == XMG_EXIT)
		{
			SM_TRACE_CRITICAL(TRMOD_APP, "appproxy_task() - receive XMG_EXIT\r\n");
			break;
		}

		if (xmsg.m_type)
		{
			SM_TRACE_INFO(TRMOD_APP,"appproxy_task() - received %s(0x%02X)\r\n",
						XMSG_NAME(xmsg.m_type), xmsg.m_type);
			proxy_state(&xmsg);
		}
		else
		{
			SM_TRACE_ERROR(TRMOD_APP,"appproxy_task() - Error in received event\r\n");
			rc = -1;
			break;
		}
	}

	proxy_end(); //should never get executed

	SM_TRACE_CRITICAL(TRMOD_APP, "appproxy_task() - return rc=%d\r\n", rc);
	return rc;
}
